home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tk / generic / tkConfig.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-31  |  33.7 KB  |  1,274 lines

  1. /* 
  2.  * tkConfig.c --
  3.  *
  4.  *    This file contains the Tk_ConfigureWidget procedure.
  5.  *
  6.  * Copyright (c) 1990-1994 The Regents of the University of California.
  7.  * Copyright (c) 1994-1995 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tkConfig.c 1.52 96/02/15 18:52:39
  13.  */
  14.  
  15. #include "tkPort.h"
  16. #include "tk.h"
  17.  
  18. /*
  19.  * Values for "flags" field of Tk_ConfigSpec structures.  Be sure
  20.  * to coordinate these values with those defined in tk.h
  21.  * (TK_CONFIG_COLOR_ONLY, etc.).  There must not be overlap!
  22.  *
  23.  * INIT -        Non-zero means (char *) things have been
  24.  *            converted to Tk_Uid's.
  25.  */
  26.  
  27. #define INIT        0x20
  28.  
  29. /*
  30.  * Forward declarations for procedures defined later in this file:
  31.  */
  32.  
  33. static int        DoConfig _ANSI_ARGS_((Tcl_Interp *interp,
  34.                 Tk_Window tkwin, Tk_ConfigSpec *specPtr,
  35.                 Tk_Uid value, int valueIsUid, char *widgRec));
  36. static Tk_ConfigSpec *    FindConfigSpec _ANSI_ARGS_((Tcl_Interp *interp,
  37.                 Tk_ConfigSpec *specs, char *argvName,
  38.                 int needFlags, int hateFlags));
  39. static char *        FormatConfigInfo _ANSI_ARGS_((Tcl_Interp *interp,
  40.                 Tk_Window tkwin, Tk_ConfigSpec *specPtr,
  41.                 char *widgRec));
  42. #ifdef STk_CODE
  43. static char *        FormatConfigValue _ANSI_ARGS_((Tcl_Interp *interp,
  44.                 Tk_Window tkwin, Tk_ConfigSpec *specPtr,
  45.                 char *widgRec, char *buffer,
  46.                 Tcl_FreeProc **freeProcPtr, int* stringp));
  47. #else
  48. static char *        FormatConfigValue _ANSI_ARGS_((Tcl_Interp *interp,
  49.                 Tk_Window tkwin, Tk_ConfigSpec *specPtr,
  50.                 char *widgRec, char *buffer,
  51.                 Tcl_FreeProc **freeProcPtr));
  52. #endif
  53.  
  54. #ifdef STk_CODE
  55.  
  56. /* This UGLY code is used only for menus items.
  57.  * It saves in the static variable menu_addr the addresse of the menu item
  58.  * we are configuring. This addresse is necessary for storing the closure
  59.  * associated to the "command" of a menu item. Address will be used to associate 
  60.  * a unique signature to this item
  61.  */
  62.  
  63. static void *menu_addr = NULL;
  64.  
  65. int
  66. Tk_Menu_ConfigureWidget(interp, addr, tkwin, specs, argc, argv, widgRec, flags)
  67.     Tcl_Interp *interp;        /* Interpreter for error reporting. */
  68.     void * addr;        /* address of the menu item */
  69.     Tk_Window tkwin;        /* Window containing widget (needed to
  70.                  * set up X resources). */
  71.     Tk_ConfigSpec *specs;    /* Describes legal options. */
  72.     int argc;            /* Number of elements in argv. */
  73.     char **argv;        /* Command-line options. */
  74.     char *widgRec;        /* Record whose fields are to be
  75.                  * modified.  Values must be properly
  76.                  * initialized. */
  77.     int flags;            /* Used to specify additional flags
  78.                  * that must be present in config specs
  79.                  * for them to be considered.  Also,
  80.                  * may have TK_CONFIG_ARGV_ONLY set. */
  81. {
  82.   int res ;
  83.   
  84.   /* This is a fluid-let :-) */
  85.   menu_addr = addr;
  86.   res = Tk_ConfigureWidget(interp, tkwin, specs, argc, argv, widgRec, flags);
  87.   menu_addr = NULL;
  88.   return res;
  89. }
  90. #endif
  91.  
  92. /*
  93.  *--------------------------------------------------------------
  94.  *
  95.  * Tk_ConfigureWidget --
  96.  *
  97.  *    Process command-line options and database options to
  98.  *    fill in fields of a widget record with resources and
  99.  *    other parameters.
  100.  *
  101.  * Results:
  102.  *    A standard Tcl return value.  In case of an error,
  103.  *    interp->result will hold an error message.
  104.  *
  105.  * Side effects:
  106.  *    The fields of widgRec get filled in with information
  107.  *    from argc/argv and the option database.  Old information
  108.  *    in widgRec's fields gets recycled.
  109.  *
  110.  *--------------------------------------------------------------
  111.  */
  112.  
  113. int
  114. Tk_ConfigureWidget(interp, tkwin, specs, argc, argv, widgRec, flags)
  115.     Tcl_Interp *interp;        /* Interpreter for error reporting. */
  116.     Tk_Window tkwin;        /* Window containing widget (needed to
  117.                  * set up X resources). */
  118.     Tk_ConfigSpec *specs;    /* Describes legal options. */
  119.     int argc;            /* Number of elements in argv. */
  120.     char **argv;        /* Command-line options. */
  121.     char *widgRec;        /* Record whose fields are to be
  122.                  * modified.  Values must be properly
  123.                  * initialized. */
  124.     int flags;            /* Used to specify additional flags
  125.                  * that must be present in config specs
  126.                  * for them to be considered.  Also,
  127.                  * may have TK_CONFIG_ARGV_ONLY set. */
  128. {
  129.     register Tk_ConfigSpec *specPtr;
  130.     Tk_Uid value;        /* Value of option from database. */
  131.     int needFlags;        /* Specs must contain this set of flags
  132.                  * or else they are not considered. */
  133.     int hateFlags;        /* If a spec contains any bits here, it's
  134.                  * not considered. */
  135.  
  136.     needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
  137.     if (Tk_Depth(tkwin) <= 1) {
  138.     hateFlags = TK_CONFIG_COLOR_ONLY;
  139.     } else {
  140.     hateFlags = TK_CONFIG_MONO_ONLY;
  141.     }
  142.  
  143.     /*
  144.      * Pass one:  scan through all the option specs, replacing strings
  145.      * with Tk_Uids (if this hasn't been done already) and clearing
  146.      * the TK_CONFIG_OPTION_SPECIFIED flags.
  147.      */
  148.  
  149.     for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
  150.     if (!(specPtr->specFlags & INIT) && (specPtr->argvName != NULL)) {
  151.         if (specPtr->dbName != NULL) {
  152.         specPtr->dbName = Tk_GetUid(specPtr->dbName);
  153.         }
  154.         if (specPtr->dbClass != NULL) {
  155.         specPtr->dbClass = Tk_GetUid(specPtr->dbClass);
  156.         }
  157.         if (specPtr->defValue != NULL) {
  158.         specPtr->defValue = Tk_GetUid(specPtr->defValue);
  159.         }
  160.     }
  161.     specPtr->specFlags = (specPtr->specFlags & ~TK_CONFIG_OPTION_SPECIFIED)
  162.         | INIT;
  163.     }
  164.  
  165.     /*
  166.      * Pass two:  scan through all of the arguments, processing those
  167.      * that match entries in the specs.
  168.      */
  169.  
  170.     for ( ; argc > 0; argc -= 2, argv += 2) {
  171.     specPtr = FindConfigSpec(interp, specs, *argv, needFlags, hateFlags);
  172.     if (specPtr == NULL) {
  173.         return TCL_ERROR;
  174.     }
  175.  
  176.     /*
  177.      * Process the entry.
  178.      */
  179.  
  180.     if (argc < 2) {
  181.         Tcl_AppendResult(interp, "value for \"", *argv,
  182.             "\" missing", (char *) NULL);
  183.         return TCL_ERROR;
  184.     }
  185.     if (DoConfig(interp, tkwin, specPtr, argv[1], 0, widgRec) != TCL_OK) {
  186.         char msg[100];
  187.  
  188.         sprintf(msg, "\n    (processing \"%.40s\" option)",
  189.             specPtr->argvName);
  190.         Tcl_AddErrorInfo(interp, msg);
  191.         return TCL_ERROR;
  192.     }
  193.     specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED;
  194.     }
  195.  
  196.     /*
  197.      * Pass three:  scan through all of the specs again;  if no
  198.      * command-line argument matched a spec, then check for info
  199.      * in the option database.  If there was nothing in the
  200.      * database, then use the default.
  201.      */
  202.  
  203.     if (!(flags & TK_CONFIG_ARGV_ONLY)) {
  204.     for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
  205.         if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)
  206.             || (specPtr->argvName == NULL)
  207.             || (specPtr->type == TK_CONFIG_SYNONYM)) {
  208.         continue;
  209.         }
  210.         if (((specPtr->specFlags & needFlags) != needFlags)
  211.             || (specPtr->specFlags & hateFlags)) {
  212.         continue;
  213.         }
  214.         value = NULL;
  215.         if (specPtr->dbName != NULL) {
  216.         value = Tk_GetOption(tkwin, specPtr->dbName, specPtr->dbClass);
  217.         }
  218.         if (value != NULL) {
  219.         if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
  220.             TCL_OK) {
  221.             char msg[200];
  222.     
  223.             sprintf(msg, "\n    (%s \"%.50s\" in widget \"%.50s\")",
  224.                 "database entry for",
  225.                 specPtr->dbName, Tk_PathName(tkwin));
  226.             Tcl_AddErrorInfo(interp, msg);
  227.             return TCL_ERROR;
  228.         }
  229.         } else {
  230.         value = specPtr->defValue;
  231.         if ((value != NULL) && !(specPtr->specFlags
  232.             & TK_CONFIG_DONT_SET_DEFAULT)) {
  233.             if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
  234.                 TCL_OK) {
  235.             char msg[200];
  236.     
  237.             sprintf(msg,
  238.                 "\n    (%s \"%.50s\" in widget \"%.50s\")",
  239.                 "default value for",
  240.                 specPtr->dbName, Tk_PathName(tkwin));
  241.             Tcl_AddErrorInfo(interp, msg);
  242.             return TCL_ERROR;
  243.             }
  244.         }
  245.         }
  246.     }
  247.     }
  248.  
  249.     return TCL_OK;
  250. }
  251.  
  252. /*
  253.  *--------------------------------------------------------------
  254.  *
  255.  * FindConfigSpec --
  256.  *
  257.  *    Search through a table of configuration specs, looking for
  258.  *    one that matches a given argvName.
  259.  *
  260.  * Results:
  261.  *    The return value is a pointer to the matching entry, or NULL
  262.  *    if nothing matched.  In that case an error message is left
  263.  *    in interp->result.
  264.  *
  265.  * Side effects:
  266.  *    None.
  267.  *
  268.  *--------------------------------------------------------------
  269.  */
  270.  
  271. static Tk_ConfigSpec *
  272. FindConfigSpec(interp, specs, argvName, needFlags, hateFlags)
  273.     Tcl_Interp *interp;        /* Used for reporting errors. */
  274.     Tk_ConfigSpec *specs;    /* Pointer to table of configuration
  275.                  * specifications for a widget. */
  276.     char *argvName;        /* Name (suitable for use in a "config"
  277.                  * command) identifying particular option. */
  278.     int needFlags;        /* Flags that must be present in matching
  279.                  * entry. */
  280.     int hateFlags;        /* Flags that must NOT be present in
  281.                  * matching entry. */
  282. {
  283.     register Tk_ConfigSpec *specPtr;
  284.     register char c;        /* First character of current argument. */
  285.     Tk_ConfigSpec *matchPtr;    /* Matching spec, or NULL. */
  286.     size_t length;
  287.  
  288.     c = argvName[1];
  289.     length = strlen(argvName);
  290.     matchPtr = NULL;
  291.     for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
  292.     if (specPtr->argvName == NULL) {
  293.         continue;
  294.     }
  295.     if ((specPtr->argvName[1] != c)
  296.         || (strncmp(specPtr->argvName, argvName, length) != 0)) {
  297.         continue;
  298.     }
  299.     if (((specPtr->specFlags & needFlags) != needFlags)
  300.         || (specPtr->specFlags & hateFlags)) {
  301.         continue;
  302.     }
  303.     if (specPtr->argvName[length] == 0) {
  304.         matchPtr = specPtr;
  305.         goto gotMatch;
  306.     }
  307.     if (matchPtr != NULL) {
  308.         Tcl_AppendResult(interp, "ambiguous option \"", argvName,
  309.             "\"", (char *) NULL);
  310.         return (Tk_ConfigSpec *) NULL;
  311.     }
  312.     matchPtr = specPtr;
  313.     }
  314.  
  315.     if (matchPtr == NULL) {
  316.     Tcl_AppendResult(interp, "unknown option \"", argvName,
  317.         "\"", (char *) NULL);
  318.     return (Tk_ConfigSpec *) NULL;
  319.     }
  320.  
  321.     /*
  322.      * Found a matching entry.  If it's a synonym, then find the
  323.      * entry that it's a synonym for.
  324.      */
  325.  
  326.     gotMatch:
  327.     specPtr = matchPtr;
  328.     if (specPtr->type == TK_CONFIG_SYNONYM) {
  329.     for (specPtr = specs; ; specPtr++) {
  330.         if (specPtr->type == TK_CONFIG_END) {
  331.         Tcl_AppendResult(interp,
  332.             "couldn't find synonym for option \"",
  333.             argvName, "\"", (char *) NULL);
  334.         return (Tk_ConfigSpec *) NULL;
  335.         }
  336.         if ((specPtr->dbName == matchPtr->dbName) 
  337.             && (specPtr->type != TK_CONFIG_SYNONYM)
  338.             && ((specPtr->specFlags & needFlags) == needFlags)
  339.             && !(specPtr->specFlags & hateFlags)) {
  340.         break;
  341.         }
  342.     }
  343.     }
  344.     return specPtr;
  345. }
  346.  
  347. /*
  348.  *--------------------------------------------------------------
  349.  *
  350.  * DoConfig --
  351.  *
  352.  *    This procedure applies a single configuration option
  353.  *    to a widget record.
  354.  *
  355.  * Results:
  356.  *    A standard Tcl return value.
  357.  *
  358.  * Side effects:
  359.  *    WidgRec is modified as indicated by specPtr and value.
  360.  *    The old value is recycled, if that is appropriate for
  361.  *    the value type.
  362.  *
  363.  *--------------------------------------------------------------
  364.  */
  365.  
  366. static int
  367. DoConfig(interp, tkwin, specPtr, value, valueIsUid, widgRec)
  368.     Tcl_Interp *interp;        /* Interpreter for error reporting. */
  369.     Tk_Window tkwin;        /* Window containing widget (needed to
  370.                  * set up X resources). */
  371.     Tk_ConfigSpec *specPtr;    /* Specifier to apply. */
  372.     char *value;        /* Value to use to fill in widgRec. */
  373.     int valueIsUid;        /* Non-zero means value is a Tk_Uid;
  374.                  * zero means it's an ordinary string. */
  375.     char *widgRec;        /* Record whose fields are to be
  376.                  * modified.  Values must be properly
  377.                  * initialized. */
  378. {
  379.     char *ptr;
  380.     Tk_Uid uid;
  381.     int nullValue;
  382.  
  383.     nullValue = 0;
  384.     if ((*value == 0) && (specPtr->specFlags & TK_CONFIG_NULL_OK)) {
  385.     nullValue = 1;
  386.     }
  387.  
  388.     do {
  389.     ptr = widgRec + specPtr->offset;
  390.     switch (specPtr->type) {
  391.         case TK_CONFIG_BOOLEAN:
  392.         if (Tcl_GetBoolean(interp, value, (int *) ptr) != TCL_OK) {
  393.             return TCL_ERROR;
  394.         }
  395.         break;
  396.         case TK_CONFIG_INT:
  397.         if (Tcl_GetInt(interp, value, (int *) ptr) != TCL_OK) {
  398.             return TCL_ERROR;
  399.         }
  400.         break;
  401.         case TK_CONFIG_DOUBLE:
  402.         if (Tcl_GetDouble(interp, value, (double *) ptr) != TCL_OK) {
  403.             return TCL_ERROR;
  404.         }
  405.         break;
  406. #ifdef STk_CODE
  407.         case TK_CONFIG_CLOSURE: {
  408.             char buffer[50], *s = "";
  409.         SCM p;
  410.  
  411.         if (*value) {
  412.           if (!STk_valid_callback(value, &p)) {
  413.           BadSpec:    
  414.             Tcl_AppendResult(interp, "bad closure specification \"",
  415.                              value, "\"", (char *) NULL);
  416.             return TCL_ERROR;
  417.           }
  418.           if (p != NULL) {
  419.             if (menu_addr != NULL) {
  420.               sprintf(buffer, "%x", menu_addr);
  421.               s = buffer;
  422.             }
  423.             
  424.             /* add this closure to the callback table */
  425.             STk_add_callback(Tk_PathName(tkwin), specPtr->argvName, s, p);
  426.           }
  427.         }
  428.         }
  429.         /* NOBREAK */
  430.         /* And now continue to register this command as a string */
  431.         case TK_CONFIG_SINT:
  432.         case TK_CONFIG_SBOOLEAN:
  433.         case TK_CONFIG_BSTRING:
  434. #endif
  435.         case TK_CONFIG_STRING: {
  436.         char *old, *new;
  437.  
  438.         if (nullValue) {
  439.             new = NULL;
  440.         } else {
  441.             new = (char *) ckalloc((unsigned) (strlen(value) + 1));
  442.             strcpy(new, value);
  443.         }
  444.         old = *((char **) ptr);
  445.         if (old != NULL) {
  446.             ckfree(old);
  447.         }
  448.         *((char **) ptr) = new;
  449.         break;
  450.         }
  451. #ifdef STk_CODE
  452.         case TK_CONFIG_MENU: {
  453.         char *old, *new;
  454.  
  455.         if (nullValue) {
  456.             new = NULL;
  457.         } else {
  458.             new = (char *) ckalloc((unsigned) (strlen(value) + 3));
  459.             new[0] = '#';
  460.             new[1] = '.';
  461.             strcpy(new+2, value);
  462.         }
  463.         old = *((char **) ptr);
  464.         if (old != NULL) {
  465.             ckfree(old);
  466.         }
  467.         *((char **) ptr) = new;
  468.         break;
  469.         }
  470.  
  471. #endif
  472.         case TK_CONFIG_UID:
  473.         if (nullValue) {
  474.             *((Tk_Uid *) ptr) = NULL;
  475.         } else {
  476.             uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  477.             *((Tk_Uid *) ptr) = uid;
  478.         }
  479.         break;
  480.         case TK_CONFIG_COLOR: {
  481.         XColor *newPtr, *oldPtr;
  482.  
  483.         if (nullValue) {
  484.             newPtr = NULL;
  485.         } else {
  486.             uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  487.             newPtr = Tk_GetColor(interp, tkwin, uid);
  488.             if (newPtr == NULL) {
  489.             return TCL_ERROR;
  490.             }
  491.         }
  492.         oldPtr = *((XColor **) ptr);
  493.         if (oldPtr != NULL) {
  494.             Tk_FreeColor(oldPtr);
  495.         }
  496.         *((XColor **) ptr) = newPtr;
  497.         break;
  498.         }
  499.         case TK_CONFIG_FONT: {
  500.         XFontStruct *newPtr, *oldPtr;
  501.  
  502.         if (nullValue) {
  503.             newPtr = NULL;
  504.         } else {
  505.             uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  506.             newPtr = Tk_GetFontStruct(interp, tkwin, uid);
  507.             if (newPtr == NULL) {
  508.             return TCL_ERROR;
  509.             }
  510.         }
  511.         oldPtr = *((XFontStruct **) ptr);
  512.         if (oldPtr != NULL) {
  513.             Tk_FreeFontStruct(oldPtr);
  514.         }
  515.         *((XFontStruct **) ptr) = newPtr;
  516.         break;
  517.         }
  518.         case TK_CONFIG_BITMAP: {
  519.         Pixmap new, old;
  520.  
  521.         if (nullValue) {
  522.             new = None;
  523.             } else {
  524.             uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  525.             new = Tk_GetBitmap(interp, tkwin, uid);
  526.             if (new == None) {
  527.             return TCL_ERROR;
  528.             }
  529.         }
  530.         old = *((Pixmap *) ptr);
  531.         if (old != None) {
  532.             Tk_FreeBitmap(Tk_Display(tkwin), old);
  533.         }
  534.         *((Pixmap *) ptr) = new;
  535.         break;
  536.         }
  537.         case TK_CONFIG_BORDER: {
  538.         Tk_3DBorder new, old;
  539.  
  540.         if (nullValue) {
  541.             new = NULL;
  542.         } else {
  543.             uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  544.             new = Tk_Get3DBorder(interp, tkwin, uid);
  545.             if (new == NULL) {
  546.             return TCL_ERROR;
  547.             }
  548.         }
  549.         old = *((Tk_3DBorder *) ptr);
  550.         if (old != NULL) {
  551.             Tk_Free3DBorder(old);
  552.         }
  553.         *((Tk_3DBorder *) ptr) = new;
  554.         break;
  555.         }
  556.         case TK_CONFIG_RELIEF:
  557.         uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  558.         if (Tk_GetRelief(interp, uid, (int *) ptr) != TCL_OK) {
  559.             return TCL_ERROR;
  560.         }
  561.         break;
  562.         case TK_CONFIG_CURSOR:
  563.         case TK_CONFIG_ACTIVE_CURSOR: {
  564.         Tk_Cursor new, old;
  565.  
  566.         if (nullValue) {
  567.             new = None;
  568.         } else {
  569.             uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  570.             new = Tk_GetCursor(interp, tkwin, uid);
  571.             if (new == None) {
  572.             return TCL_ERROR;
  573.             }
  574.         }
  575.         old = *((Tk_Cursor *) ptr);
  576.         if (old != None) {
  577.             Tk_FreeCursor(Tk_Display(tkwin), old);
  578.         }
  579.         *((Tk_Cursor *) ptr) = new;
  580.         if (specPtr->type == TK_CONFIG_ACTIVE_CURSOR) {
  581.             Tk_DefineCursor(tkwin, new);
  582.         }
  583.         break;
  584.         }
  585.         case TK_CONFIG_JUSTIFY:
  586.         uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  587.         if (Tk_GetJustify(interp, uid, (Tk_Justify *) ptr) != TCL_OK) {
  588.             return TCL_ERROR;
  589.         }
  590.         break;
  591.         case TK_CONFIG_ANCHOR:
  592.         uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  593.         if (Tk_GetAnchor(interp, uid, (Tk_Anchor *) ptr) != TCL_OK) {
  594.             return TCL_ERROR;
  595.         }
  596.         break;
  597.         case TK_CONFIG_CAP_STYLE:
  598.         uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  599.         if (Tk_GetCapStyle(interp, uid, (int *) ptr) != TCL_OK) {
  600.             return TCL_ERROR;
  601.         }
  602.         break;
  603.         case TK_CONFIG_JOIN_STYLE:
  604.         uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
  605.         if (Tk_GetJoinStyle(interp, uid, (int *) ptr) != TCL_OK) {
  606.             return TCL_ERROR;
  607.         }
  608.         break;
  609.         case TK_CONFIG_PIXELS:
  610.         if (Tk_GetPixels(interp, tkwin, value, (int *) ptr)
  611.             != TCL_OK) {
  612.             return TCL_ERROR;
  613.         }
  614.         break;
  615.         case TK_CONFIG_MM:
  616.         if (Tk_GetScreenMM(interp, tkwin, value, (double *) ptr)
  617.             != TCL_OK) {
  618.             return TCL_ERROR;
  619.         }
  620.         break;
  621.         case TK_CONFIG_WINDOW: {
  622.         Tk_Window tkwin2;
  623.  
  624.         if (nullValue) {
  625.             tkwin2 = NULL;
  626.         } else {
  627.             tkwin2 = Tk_NameToWindow(interp, value, tkwin);
  628.             if (tkwin2 == NULL) {
  629.             return TCL_ERROR;
  630.             }
  631.         }
  632.         *((Tk_Window *) ptr) = tkwin2;
  633.         break;
  634.         }
  635.         case TK_CONFIG_CUSTOM:
  636.         if ((*specPtr->customPtr->parseProc)(
  637.             specPtr->customPtr->clientData, interp, tkwin,
  638.             value, widgRec, specPtr->offset) != TCL_OK) {
  639.             return TCL_ERROR;
  640.         }
  641.         break;
  642.         default: {
  643.         sprintf(interp->result, "bad config table: unknown type %d",
  644.             specPtr->type);
  645.         return TCL_ERROR;
  646.         }
  647.     }
  648.     specPtr++;
  649.     } while ((specPtr->argvName == NULL) && (specPtr->type != TK_CONFIG_END));
  650.     return TCL_OK;
  651. }
  652.  
  653. /*
  654.  *--------------------------------------------------------------
  655.  *
  656.  * Tk_ConfigureInfo --
  657.  *
  658.  *    Return information about the configuration options
  659.  *    for a window, and their current values.
  660.  *
  661.  * Results:
  662.  *    Always returns TCL_OK.  Interp->result will be modified
  663.  *    hold a description of either a single configuration option
  664.  *    available for "widgRec" via "specs", or all the configuration
  665.  *    options available.  In the "all" case, the result will
  666.  *    available for "widgRec" via "specs".  The result will
  667.  *    be a list, each of whose entries describes one option.
  668.  *    Each entry will itself be a list containing the option's
  669.  *    name for use on command lines, database name, database
  670.  *    class, default value, and current value (empty string
  671.  *    if none).  For options that are synonyms, the list will
  672.  *    contain only two values:  name and synonym name.  If the
  673.  *    "name" argument is non-NULL, then the only information
  674.  *    returned is that for the named argument (i.e. the corresponding
  675.  *    entry in the overall list is returned).
  676.  *
  677.  * Side effects:
  678.  *    None.
  679.  *
  680.  *--------------------------------------------------------------
  681.  */
  682.  
  683. int
  684. Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags)
  685.     Tcl_Interp *interp;        /* Interpreter for error reporting. */
  686.     Tk_Window tkwin;        /* Window corresponding to widgRec. */
  687.     Tk_ConfigSpec *specs;    /* Describes legal options. */
  688.     char *widgRec;        /* Record whose fields contain current
  689.                  * values for options. */
  690.     char *argvName;        /* If non-NULL, indicates a single option
  691.                  * whose info is to be returned.  Otherwise
  692.                  * info is returned for all options. */
  693.     int flags;            /* Used to specify additional flags
  694.                  * that must be present in config specs
  695.                  * for them to be considered. */
  696. {
  697.     register Tk_ConfigSpec *specPtr;
  698.     int needFlags, hateFlags;
  699.     char *list;
  700. #ifdef STk_CODE
  701.     char *leader = "(";
  702. #else
  703.     char *leader = "{";
  704. #endif
  705.  
  706.     needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
  707.     if (Tk_Depth(tkwin) <= 1) {
  708.     hateFlags = TK_CONFIG_COLOR_ONLY;
  709.     } else {
  710.     hateFlags = TK_CONFIG_MONO_ONLY;
  711.     }
  712.  
  713.     /*
  714.      * If information is only wanted for a single configuration
  715.      * spec, then handle that one spec specially.
  716.      */
  717.  
  718.     Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
  719.     if (argvName != NULL) {
  720.     specPtr = FindConfigSpec(interp, specs, argvName, needFlags,
  721.         hateFlags);
  722.     if (specPtr == NULL) {
  723.         return TCL_ERROR;
  724.     }
  725.     interp->result = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
  726.     interp->freeProc = TCL_DYNAMIC;
  727.     return TCL_OK;
  728.     }
  729.  
  730.     /*
  731.      * Loop through all the specs, creating a big list with all
  732.      * their information.
  733.      */
  734.  
  735.     for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
  736.     if ((argvName != NULL) && (specPtr->argvName != argvName)) {
  737.         continue;
  738.     }
  739.     if (((specPtr->specFlags & needFlags) != needFlags)
  740.         || (specPtr->specFlags & hateFlags)) {
  741.         continue;
  742.     }
  743.     if (specPtr->argvName == NULL) {
  744.         continue;
  745.     }
  746.     list = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
  747. #ifdef STk_CODE
  748.     Tcl_AppendResult(interp, leader, list, ")", (char *) NULL);
  749.     ckfree(list);
  750.     leader = " (";
  751. #else
  752.     Tcl_AppendResult(interp, leader, list, "}", (char *) NULL);
  753.     ckfree(list);
  754.     leader = " {";
  755. #endif
  756.     }
  757.     return TCL_OK;
  758. }
  759.  
  760. /*
  761.  *--------------------------------------------------------------
  762.  *
  763.  * FormatConfigInfo --
  764.  *
  765.  *    Create a valid Tcl list holding the configuration information
  766.  *    for a single configuration option.
  767.  *
  768.  * Results:
  769.  *    A Tcl list, dynamically allocated.  The caller is expected to
  770.  *    arrange for this list to be freed eventually.
  771.  *
  772.  * Side effects:
  773.  *    Memory is allocated.
  774.  *
  775.  *--------------------------------------------------------------
  776.  */
  777.  
  778. static char *
  779. FormatConfigInfo(interp, tkwin, specPtr, widgRec)
  780.     Tcl_Interp *interp;            /* Interpreter to use for things
  781.                      * like floating-point precision. */
  782.     Tk_Window tkwin;            /* Window corresponding to widget. */
  783.     register Tk_ConfigSpec *specPtr;    /* Pointer to information describing
  784.                      * option. */
  785.     char *widgRec;            /* Pointer to record holding current
  786.                      * values of info for widget. */
  787. {
  788.     char *argv[6], *result;
  789. #ifdef STk_CODE
  790. #   define MAX_BUFFER 200
  791.     char buffer[MAX_BUFFER], dflt[MAX_BUFFER];
  792.     int len, stringp;
  793. #else
  794.     char buffer[200];
  795. #endif
  796.     Tcl_FreeProc *freeProc = (Tcl_FreeProc *) NULL;
  797.  
  798.     argv[0] = specPtr->argvName;
  799.     argv[1] = specPtr->dbName;
  800.     argv[2] = specPtr->dbClass;
  801.     argv[3] = specPtr->defValue;
  802.     if (specPtr->type == TK_CONFIG_SYNONYM) {
  803. #ifdef STk_CODE
  804.       result = ckalloc(strlen(argv[0]) + strlen(argv [1]) + 4);
  805.       sprintf(result, ":%s \"%s\"", argv[0]+1, argv [1]);
  806.       return result;
  807. #else
  808.     return Tcl_Merge(2, argv);
  809. #endif
  810.     }
  811. #ifdef STk_CODE
  812.     argv[4] = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,
  813.         &freeProc, &stringp);
  814. #else
  815.     argv[4] = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,
  816.         &freeProc);
  817. #endif
  818.     if (argv[1] == NULL) {
  819.     argv[1] = "";
  820.     }
  821.     if (argv[2] == NULL) {
  822.     argv[2] = "";
  823.     }
  824. #ifdef STk_CODE
  825.     /* 
  826.      * Default value of an option (the one at index 3) can contain weird 
  827.      * characters (e.g. fonts can contain '#'). Quote it if necessary.
  828.      */
  829.     if (argv[3] == NULL) {
  830.     argv[3] = "\"\"";
  831.     }
  832.     else if (stringp) {
  833.       sprintf(dflt, "\"%s\"", argv[3]);
  834.       argv[3] = dflt;        
  835.     }
  836.     if (argv[4] == NULL) {
  837.     argv[4] = "\"\"";
  838.     }  
  839.     len = strlen(argv[0])+strlen(argv[1])+strlen(argv[2])+
  840.           strlen(argv[3])+strlen(argv[4]) + 9; /* 4 spaces, 4 quotes  and a null */
  841.  
  842.     /* copy argv array in the result string  and subsitute "-" by ":" 
  843.      * in option name. Quote also the name and the class of the
  844.      * Qutotication is a little bit simplistic here, but those parameters 
  845.      * are identifier (a priori)
  846.      */
  847.     result = ckalloc(len);      
  848.     sprintf(result, ":%s \"%s\" \"%s\" %s %s", 
  849.                 argv[0]+1,argv[1],argv[2],argv[3],argv[4]);
  850. #else
  851.     if (argv[3] == NULL) {
  852.     argv[3] = "";
  853.     }
  854.     if (argv[4] == NULL) {
  855.     argv[4] = "";
  856.     }
  857.     result = Tcl_Merge(5, argv);
  858. #endif
  859.     if (freeProc != NULL) {
  860.     if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) {
  861.         ckfree(argv[4]);
  862.     } else {
  863.         (*freeProc)(argv[4]);
  864.     }
  865.     }
  866.     return result;
  867. }
  868.  
  869. /*
  870.  *----------------------------------------------------------------------
  871.  *
  872.  * FormatConfigValue --
  873.  *
  874.  *    This procedure formats the current value of a configuration
  875.  *    option.
  876.  *
  877.  * Results:
  878.  *    The return value is the formatted value of the option given
  879.  *    by specPtr and widgRec.  If the value is static, so that it
  880.  *    need not be freed, *freeProcPtr will be set to NULL;  otherwise
  881.  *    *freeProcPtr will be set to the address of a procedure to
  882.  *    free the result, and the caller must invoke this procedure
  883.  *    when it is finished with the result.
  884.  *
  885.  * Side effects:
  886.  *    None.
  887.  *
  888.  *----------------------------------------------------------------------
  889.  */
  890.  
  891. static char *
  892. #ifndef STk_CODE
  893. FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, freeProcPtr)
  894. #else
  895. FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, freeProcPtr, stringp)
  896. #endif
  897.     Tcl_Interp *interp;        /* Interpreter for use in real conversions. */
  898.     Tk_Window tkwin;        /* Window corresponding to widget. */
  899.     Tk_ConfigSpec *specPtr;    /* Pointer to information describing option.
  900.                  * Must not point to a synonym option. */
  901.     char *widgRec;        /* Pointer to record holding current
  902.                  * values of info for widget. */
  903.     char *buffer;        /* Static buffer to use for small values.
  904.                  * Must have at least 200 bytes of storage. */
  905.     Tcl_FreeProc **freeProcPtr;    /* Pointer to word to fill in with address
  906.                  * of procedure to free the result, or NULL
  907.                  * if result is static. */
  908. #ifdef STk_CODE
  909.     int *stringp;        /* 1 if the default value of this configuration 
  910.                  * option is a string
  911.                  */
  912. #endif
  913. {
  914.     char *ptr, *result;
  915.  
  916. #ifdef STk_CODE
  917.     *stringp = 1;
  918. #endif
  919.     *freeProcPtr = NULL;
  920.     ptr = widgRec + specPtr->offset;
  921.     result = "";
  922.     switch (specPtr->type) {
  923.     case TK_CONFIG_BOOLEAN:
  924. #ifdef STk_CODE
  925.         *stringp = 0;
  926.         /* NO BREAK */
  927.         case TK_CONFIG_SBOOLEAN:
  928.         return (*((int *) ptr) == 0) ? "#f" : "#t";
  929. #else
  930.         if (*((int *) ptr) == 0) {
  931.         result = "0";
  932.         } else {
  933.         result = "1";
  934.         }
  935.         break;
  936. #endif
  937.     case TK_CONFIG_INT:
  938.         sprintf(buffer, "%d", *((int *) ptr));
  939. #ifdef STk_CODE
  940.         *stringp = 0;
  941.         return buffer;
  942. #else
  943.         result = buffer;
  944.         break;
  945. #endif
  946.     case TK_CONFIG_DOUBLE:
  947.         Tcl_PrintDouble(interp, *((double *) ptr), buffer);
  948. #ifdef STk_CODE
  949.         *stringp = 0;
  950.         return buffer;
  951. #else
  952.         result = buffer;
  953.         break;
  954. #endif
  955. #ifdef STk_CODE
  956.     case TK_CONFIG_SINT:
  957.         *stringp = 0;
  958.         result   = (*(char **) ptr);
  959.         if (result == NULL) result = "0";
  960.         return result;
  961.         case TK_CONFIG_MENU:
  962.         *stringp = 0;
  963.         result   = (*(char **) ptr);
  964.         if (result == NULL) result = "#f";
  965.         return result;
  966.         case TK_CONFIG_CLOSURE:
  967.         result = (*(char **) ptr);
  968.         if (result == NULL) {
  969.           result = "";
  970.           break;
  971.         }
  972.         else {
  973.           *stringp = 0;
  974.           return result;
  975.         }
  976.         case TK_CONFIG_BSTRING:
  977.         *stringp = 0;
  978.         /* NO BREAK */
  979. #endif
  980.     case TK_CONFIG_STRING:
  981.         result = (*(char **) ptr);
  982.         if (result == NULL) {
  983.         result = "";
  984.         }
  985.         break;
  986.     case TK_CONFIG_UID: {
  987.         Tk_Uid uid = *((Tk_Uid *) ptr);
  988.         if (uid != NULL) {
  989.         result = uid;
  990.         }
  991.         break;
  992.     }
  993.     case TK_CONFIG_COLOR: {
  994.         XColor *colorPtr = *((XColor **) ptr);
  995.         if (colorPtr != NULL) {
  996.         result = Tk_NameOfColor(colorPtr);
  997.         }
  998.         break;
  999.     }
  1000.     case TK_CONFIG_FONT: {
  1001.         XFontStruct *fontStructPtr = *((XFontStruct **) ptr);
  1002.         if (fontStructPtr != NULL) {
  1003.         result = Tk_NameOfFontStruct(fontStructPtr);
  1004.         }
  1005.         break;
  1006.     }
  1007.     case TK_CONFIG_BITMAP: {
  1008.         Pixmap pixmap = *((Pixmap *) ptr);
  1009.         if (pixmap != None) {
  1010.         result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap);
  1011.         }
  1012.         break;
  1013.     }
  1014.     case TK_CONFIG_BORDER: {
  1015.         Tk_3DBorder border = *((Tk_3DBorder *) ptr);
  1016.         if (border != NULL) {
  1017.         result = Tk_NameOf3DBorder(border);
  1018.         }
  1019.         break;
  1020.     }
  1021.     case TK_CONFIG_RELIEF:
  1022.         result = Tk_NameOfRelief(*((int *) ptr));
  1023.         break;
  1024.     case TK_CONFIG_CURSOR:
  1025.     case TK_CONFIG_ACTIVE_CURSOR: {
  1026.         Tk_Cursor cursor = *((Tk_Cursor *) ptr);
  1027.         if (cursor != None) {
  1028.         result = Tk_NameOfCursor(Tk_Display(tkwin), cursor);
  1029.         }
  1030.         break;
  1031.     }
  1032.     case TK_CONFIG_JUSTIFY:
  1033.         result = Tk_NameOfJustify(*((Tk_Justify *) ptr));
  1034.         break;
  1035.     case TK_CONFIG_ANCHOR:
  1036.         result = Tk_NameOfAnchor(*((Tk_Anchor *) ptr));
  1037.         break;
  1038.     case TK_CONFIG_CAP_STYLE:
  1039.         result = Tk_NameOfCapStyle(*((int *) ptr));
  1040.         break;
  1041.     case TK_CONFIG_JOIN_STYLE:
  1042.         result = Tk_NameOfJoinStyle(*((int *) ptr));
  1043.         break;
  1044.     case TK_CONFIG_PIXELS:
  1045.         sprintf(buffer, "%d", *((int *) ptr));
  1046. #ifdef STk_CODE
  1047.         *stringp = 0; /* most of the time correct "2c" will be seen as 
  1048.                * the symbol 2c but this should be rare */
  1049.         return buffer;
  1050. #else
  1051.         result = buffer;
  1052.         break;
  1053. #endif
  1054.     case TK_CONFIG_MM:
  1055.         Tcl_PrintDouble(interp, *((double *) ptr), buffer);
  1056. #ifdef STk_CODE
  1057.         *stringp = 0;
  1058.         return buffer;
  1059. #else
  1060.         result = buffer;
  1061.         break;
  1062. #endif
  1063.     case TK_CONFIG_WINDOW: {
  1064.         Tk_Window tkwin;
  1065.  
  1066.         tkwin = *((Tk_Window *) ptr);
  1067.         if (tkwin != NULL) {
  1068.         result = Tk_PathName(tkwin);
  1069.         }
  1070.         break;
  1071.     }
  1072.     case TK_CONFIG_CUSTOM:
  1073.         result = (*specPtr->customPtr->printProc)(
  1074.             specPtr->customPtr->clientData, tkwin, widgRec,
  1075.             specPtr->offset, freeProcPtr);
  1076. #ifdef STk_CODE
  1077.         *stringp = 0;
  1078.         return result;
  1079. #endif
  1080.         break;
  1081.     default: 
  1082.         result = "?? unknown type ??";
  1083.     }
  1084. #ifdef STk_CODE
  1085.     /* result contain a value which must be converted to a string */
  1086.     if (result == NULL) {
  1087.       return  "\"\"";
  1088.     }
  1089.     else {
  1090.       register char *s, *d;
  1091.       int len;
  1092.       char *r              = buffer;
  1093.       Tcl_FreeProc *oldFree = *freeProcPtr;
  1094.  
  1095.       *freeProcPtr = (Tcl_FreeProc *) NULL;
  1096.       len          = strlen(result);
  1097.  
  1098.       if (len > (200/2)-3) {
  1099.     r = ckalloc(len * 2 + 3); /* worst overestimation */
  1100.     *freeProcPtr = (Tcl_FreeProc *) free;
  1101.       }
  1102.  
  1103.       d = r; *d++ = '"';
  1104.       for (s = result; *s; s++, d++) {
  1105.     if (*s == '"' || *s == '\\') *d++ = '\\';
  1106.     *d = *s;
  1107.       }
  1108.       *d++ = '"';
  1109.       *d   = '\0';
  1110.  
  1111.       if (oldFree != NULL) {
  1112.     /* 
  1113.      * oldFree could be non NULL iff we have TK_CONFIG_CUSTOM before.
  1114.      * In this case result points something which must be unallocated
  1115.      *
  1116.      */
  1117.     if (oldFree == (Tcl_FreeProc *) free) {
  1118.         ckfree(result);
  1119.     } else {
  1120.         (*oldFree)(result);
  1121.     }
  1122.       }
  1123.       return r;
  1124.     }
  1125. #else
  1126.     return result;
  1127. #endif
  1128. }
  1129.  
  1130. /*
  1131.  *----------------------------------------------------------------------
  1132.  *
  1133.  * Tk_ConfigureValue --
  1134.  *
  1135.  *    This procedure returns the current value of a configuration
  1136.  *    option for a widget.
  1137.  *
  1138.  * Results:
  1139.  *    The return value is a standard Tcl completion code (TCL_OK or
  1140.  *    TCL_ERROR).  Interp->result will be set to hold either the value
  1141.  *    of the option given by argvName (if TCL_OK is returned) or
  1142.  *    an error message (if TCL_ERROR is returned).
  1143.  *
  1144.  * Side effects:
  1145.  *    None.
  1146.  *
  1147.  *----------------------------------------------------------------------
  1148.  */
  1149.  
  1150. int
  1151. Tk_ConfigureValue(interp, tkwin, specs, widgRec, argvName, flags)
  1152.     Tcl_Interp *interp;        /* Interpreter for error reporting. */
  1153.     Tk_Window tkwin;        /* Window corresponding to widgRec. */
  1154.     Tk_ConfigSpec *specs;    /* Describes legal options. */
  1155.     char *widgRec;        /* Record whose fields contain current
  1156.                  * values for options. */
  1157.     char *argvName;        /* Gives the command-line name for the
  1158.                  * option whose value is to be returned. */
  1159.     int flags;            /* Used to specify additional flags
  1160.                  * that must be present in config specs
  1161.                  * for them to be considered. */
  1162. {
  1163.     Tk_ConfigSpec *specPtr;
  1164.     int needFlags, hateFlags;
  1165. #ifdef STk_CODE
  1166.     int dumb;
  1167. #endif
  1168.  
  1169.     needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
  1170.     if (Tk_Depth(tkwin) <= 1) {
  1171.     hateFlags = TK_CONFIG_COLOR_ONLY;
  1172.     } else {
  1173.     hateFlags = TK_CONFIG_MONO_ONLY;
  1174.     }
  1175.     specPtr = FindConfigSpec(interp, specs, argvName, needFlags, hateFlags);
  1176.     if (specPtr == NULL) {
  1177.     return TCL_ERROR;
  1178.     }
  1179. #ifdef STk_CODE
  1180.     interp->result = FormatConfigValue(interp, tkwin, specPtr, widgRec,
  1181.         interp->result, &interp->freeProc, &dumb);
  1182. #else
  1183.     interp->result = FormatConfigValue(interp, tkwin, specPtr, widgRec,
  1184.         interp->result, &interp->freeProc);
  1185. #endif
  1186.     return TCL_OK;
  1187. }
  1188.  
  1189. /*
  1190.  *----------------------------------------------------------------------
  1191.  *
  1192.  * Tk_FreeOptions --
  1193.  *
  1194.  *    Free up all resources associated with configuration options.
  1195.  *
  1196.  * Results:
  1197.  *    None.
  1198.  *
  1199.  * Side effects:
  1200.  *    Any resource in widgRec that is controlled by a configuration
  1201.  *    option (e.g. a Tk_3DBorder or XColor) is freed in the appropriate
  1202.  *    fashion.
  1203.  *
  1204.  *----------------------------------------------------------------------
  1205.  */
  1206.  
  1207.     /* ARGSUSED */
  1208. void
  1209. Tk_FreeOptions(specs, widgRec, display, needFlags)
  1210.     Tk_ConfigSpec *specs;    /* Describes legal options. */
  1211.     char *widgRec;        /* Record whose fields contain current
  1212.                  * values for options. */
  1213.     Display *display;        /* X display; needed for freeing some
  1214.                  * resources. */
  1215.     int needFlags;        /* Used to specify additional flags
  1216.                  * that must be present in config specs
  1217.                  * for them to be considered. */
  1218. {
  1219.     register Tk_ConfigSpec *specPtr;
  1220.     char *ptr;
  1221.  
  1222.     for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
  1223.     if ((specPtr->specFlags & needFlags) != needFlags) {
  1224.         continue;
  1225.     }
  1226.     ptr = widgRec + specPtr->offset;
  1227.     switch (specPtr->type) {
  1228. #ifdef STk_CODE
  1229.         case TK_CONFIG_CLOSURE:
  1230.         case TK_CONFIG_MENU:
  1231.         case TK_CONFIG_SINT:
  1232.         case TK_CONFIG_SBOOLEAN:
  1233.         case TK_CONFIG_BSTRING:
  1234. #endif
  1235.         case TK_CONFIG_STRING:
  1236.         if (*((char **) ptr) != NULL) {
  1237.             ckfree(*((char **) ptr));
  1238.             *((char **) ptr) = NULL;
  1239.         }
  1240.         break;
  1241.         case TK_CONFIG_COLOR:
  1242.         if (*((XColor **) ptr) != NULL) {
  1243.             Tk_FreeColor(*((XColor **) ptr));
  1244.             *((XColor **) ptr) = NULL;
  1245.         }
  1246.         break;
  1247.         case TK_CONFIG_FONT:
  1248.         if (*((XFontStruct **) ptr) != NULL) {
  1249.             Tk_FreeFontStruct(*((XFontStruct **) ptr));
  1250.             *((XFontStruct **) ptr) = NULL;
  1251.         }
  1252.         break;
  1253.         case TK_CONFIG_BITMAP:
  1254.         if (*((Pixmap *) ptr) != None) {
  1255.             Tk_FreeBitmap(display, *((Pixmap *) ptr));
  1256.             *((Pixmap *) ptr) = None;
  1257.         }
  1258.         break;
  1259.         case TK_CONFIG_BORDER:
  1260.         if (*((Tk_3DBorder *) ptr) != NULL) {
  1261.             Tk_Free3DBorder(*((Tk_3DBorder *) ptr));
  1262.             *((Tk_3DBorder *) ptr) = NULL;
  1263.         }
  1264.         break;
  1265.         case TK_CONFIG_CURSOR:
  1266.         case TK_CONFIG_ACTIVE_CURSOR:
  1267.         if (*((Tk_Cursor *) ptr) != None) {
  1268.             Tk_FreeCursor(display, *((Tk_Cursor *) ptr));
  1269.             *((Tk_Cursor *) ptr) = None;
  1270.         }
  1271.     }
  1272.     }
  1273. }
  1274.